package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.model.CartInfo;
import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.product.model.SkuInfo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: atguigu
 * @create: 2023-05-05 10:46
 */
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private ProductFeignClient productFeignClient;


    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 将商品加入到购物车
     *
     * @param userId 用户ID
     * @param skuId  商品SKUID
     * @param skuNum 商品数量
     * @return
     */
    @Override
    public void addToCart(String userId, Long skuId, Integer skuNum) {
        //1.远程调用商品微服务获取商品信息 TODO 改为异步操作-从缓存中读取
        SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
        //2.远程调用商品微服务获取商品价格
        BigDecimal skuPrice = productFeignClient.getSkuPrice(skuId);

        //3.构建用户购物车hash结构Key
        String cartKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        //3.1 创建操作hash类型操作对象 绑定某个Key
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        //4.将用户购物车商品存入Redis 判断商品是否存在
        Boolean flag = hashOps.hasKey(skuId.toString());
        CartInfo cartInfo = null;
        if (flag) {
            //4.1 存在 购物车商品数量累加
            cartInfo = hashOps.get(skuId.toString());
            cartInfo.setSkuNum(cartInfo.getSkuNum() + skuNum);
        } else {
            //4.2 不存在 新增购物车商品
            cartInfo = new CartInfo();
            BeanUtils.copyProperties(skuInfo, cartInfo);
            cartInfo.setUserId(userId);
            cartInfo.setSkuId(skuId);
            cartInfo.setCartPrice(skuPrice);
            cartInfo.setSkuPrice(skuPrice);
            cartInfo.setSkuNum(skuNum);
            cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfo.setCreateTime(new Date());
            cartInfo.setUpdateTime(new Date());
        }
        hashOps.put(skuId.toString(), cartInfo);
    }

    /**
     * 初版: 分别查询已登录,或者未登录购物车列表 不考虑合并
     *
     * @param userId     登录用户ID
     * @param userTempId 临时用户ID
     * @return
     */
    //@Override
    //public List<CartInfo> getCartList(String userId, String userTempId) {
    //    List<CartInfo> loginCartList = null;
    //    //1.判断登录用户ID是否有值  查询已登录购物车列表 并且返回
    //    if (StringUtils.isNotBlank(userId)) {
    //        String redisKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    //        BoundHashOperations<String, String, CartInfo> loginHashOps = redisTemplate.boundHashOps(redisKey);
    //        loginCartList = loginHashOps.values();
    //        return loginCartList;
    //    }
    //
    //    //2.判断临时用户ID是否有值  查询未登录购物车列表 并且返回
    //    List<CartInfo> noLoginCartList = null;
    //    if (StringUtils.isNotBlank(userTempId)) {
    //        String redisKey = RedisConst.USER_KEY_PREFIX + userTempId + RedisConst.USER_CART_KEY_SUFFIX;
    //        BoundHashOperations<String, String, CartInfo> noLoginHashOps = redisTemplate.boundHashOps(redisKey);
    //        noLoginCartList = noLoginHashOps.values();
    //        return noLoginCartList;
    //    }
    //    return null;
    //}


    /**
     * 进阶: 分别查询已登录,或者未登录购物车列表 合并
     *
     * @param userId     登录用户ID
     * @param userTempId 临时用户ID
     * @return
     */
    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {
        //1.判断临时用户ID是否有值  查询未登录购物车列表 并且返回
        List<CartInfo> noLoginCartList = null;
        if (StringUtils.isNotBlank(userTempId)) {
            String redisKey = RedisConst.USER_KEY_PREFIX + userTempId + RedisConst.USER_CART_KEY_SUFFIX;
            BoundHashOperations<String, String, CartInfo> noLoginHashOps = redisTemplate.boundHashOps(redisKey);
            noLoginCartList = noLoginHashOps.values();
        }
        //1.1 如果用户未登录 直接返回未登录购物车列表即可
        if (StringUtils.isBlank(userId)) {
            //1.2 对购物车集合进行排序
            noLoginCartList = noLoginCartList.stream().sorted((o1, o2) -> {
                //比较相邻两个购物车对象中创建时间
                return DateUtil.truncatedCompareTo(o1.getCreateTime(), o2.getCreateTime(), Calendar.SECOND);
            }).collect(Collectors.toList());
            return noLoginCartList;
        }

        //2.说明真正用户登录了
        //2.1 判断登录用户ID是否有值  查询已登录购物车列表 并且返回
        String loginRedisKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        BoundHashOperations<String, String, CartInfo> loginHashOps = redisTemplate.boundHashOps(loginRedisKey);

        //2.2 判断未登录购物车有数据跟当前登录购物车列表合并
        if (!CollectionUtils.isEmpty(noLoginCartList)) {
            //2.3 遍历未登录购物车列表 判断 当前登录购物车hash中是否包含当前商品SkuID
            for (CartInfo noLoginCartInfo : noLoginCartList) {
                String hashKey = noLoginCartInfo.getSkuId().toString();
                if (loginHashOps.hasKey(hashKey)) {
                    //包含该商品
                    CartInfo loginCartInfo = loginHashOps.get(hashKey);
                    //更新数量
                    loginCartInfo.setSkuNum(loginCartInfo.getSkuNum() + noLoginCartInfo.getSkuNum());
                    loginCartInfo.setUpdateTime(new Date());
                    //更新选中状态
                    loginHashOps.put(hashKey, loginCartInfo);
                } else {
                    //已登录购物车不包含该商品 修改未登录购物车商品中 用户ID
                    noLoginCartInfo.setUserId(userId);
                    loginHashOps.put(hashKey, noLoginCartInfo);
                }
            }
        }
        //3.合并后将未登录购物车数据删除
        String noLogRedisKey = RedisConst.USER_KEY_PREFIX + userTempId + RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.delete(noLogRedisKey);

        //4.查询已登录购物车列表
        List<CartInfo> loginCartList = loginHashOps.values();
        if (!CollectionUtils.isEmpty(loginCartList)) {
            List<CartInfo> cartInfoList = loginCartList.stream().sorted((o1, o2) -> {
                return DateUtil.truncatedCompareTo(o1.getCreateTime(), o2.getCreateTime(), Calendar.SECOND);
            }).collect(Collectors.toList());
            return cartInfoList;
        }
        return null;
    }

    /**
     * 变更用户购物车商品选中状态
     *
     * @param userId
     * @param skuId
     * @param isChecked
     */
    @Override
    public void checkCart(String userId, Long skuId, Integer isChecked) {
        String redisKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(redisKey);
        if (hashOps.hasKey(skuId.toString())) {
            CartInfo cartInfo = hashOps.get(skuId.toString());
            cartInfo.setIsChecked(isChecked);
            hashOps.put(skuId.toString(), cartInfo);
        }
    }

    /**
     * 删除指定购物车商品
     *
     * @param userId
     * @param skuId
     * @return
     */
    @Override
    public void deleteCart(String userId, Long skuId) {
        String redisKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(redisKey);
        hashOps.delete(skuId.toString());
    }


    /**
     * 查询指定用户选中购物车商品列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        //1.构建用户购物车hash结构key
        String cartKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        //2.查询购物车列表,对购物数据进行过滤
        if(!CollectionUtils.isEmpty(cartInfoList)){
            cartInfoList = cartInfoList.stream().filter(cartInfo -> {
                // true :需要数据   false:不需要的数据
                return cartInfo.getIsChecked().intValue() == 1;
            }).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(cartInfoList)) {
            throw new RuntimeException("没有需要结算商品!");
        }
        return cartInfoList;
    }
}
